<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Section 14.2.&nbsp; Session Security</title>
<link rel="STYLESHEET" type="text/css" href="images/style.css">
<link rel="STYLESHEET" type="text/css" href="images/docsafari.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14-SECT-1.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14-SECT-3.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<br><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr><TD valign="top"><a name="learnphpmysql-CHP-14-SECT-2"></a>
<h3 id="title-IDAMOG1H" class="docSection1Title">14.2. Session Security</h3>
<a name="IDX-CHP-14-0644"></a> 
<a name="IDX-CHP-14-0645"></a> 

<p class="docText">Because a session may contain sensitive information, you need to treat the session as a possible security hole. Session security is necessary to create and implement a session. If someone is listening in or snooping on a network, it's possible that he can intercept a session ID and use it to look like he is someone else. It's also possible to access session data from the local filesystem on multiuser systems such as ISP hosting machines.</p>
<a name="learnphpmysql-CHP-14-SECT-2.1"></a>
<h4 id="title-IDA2OG1H" class="docSection2Title">14.2.1. Session Hijacking and Session Fixation</h4>
<p class="docText"><span class="docEmphasis">Session hijacking</span><a name="IDX-CHP-14-0646"></a> 
<a name="IDX-CHP-14-0647"></a> 
 is when someone accesses either a client's cookie or session ID, and then attempts to use this data. <span class="docEmphasis">Session fixation</span><a name="IDX-CHP-14-0648"></a> 
<a name="IDX-CHP-14-0649"></a> 
 is attempting to set your own session ID. Session fixation and hijacking are easy to combat. We'll make use of the super global variables for the client's IP address and browser type to keep things secure.</p>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-EX-8">Example 14-8</a> demonstrates encoding the information with an <tt>md5</tt> function call to thwart these potential security holes.</p>
<a name="learnphpmysql-CHP-14-EX-8"></a><h5 id="title-IDAIQG1H" class="docExampleTitle">Example 14-8. Checking for session hijacking</h5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><td>

<pre>
&lt;?php
session_start();
$user_check = md5($_SERVER['HTTP_USER_AGENT'] . $_SERVER['REMOTE_ADDR']);
if (empty($_SESSION['user_data'])) {
session_regenerate_id();
echo ("New session, saving user_check.");
$_SESSION['user_data'] = $user_check;
}
if (strcmp($_SESSION['user_data'], $user_check) !== 0) {
session_regenerate_id();
echo ("Warning, you must reenter your session.");
$_SESSION = array();
$_SESSION['user_data'] = $user_check;
}
else {
echo ("Connection verified!");
}
?&gt;
</pre><BR>

</td></tr></table></P>
<p class="docText">When a browser first requests the page in <a class="docLink" href="#learnphpmysql-CHP-14-EX-8">Example 14-8</a>, a session is started. In that session, we stored the encoded combination of the IP address and browser type. That way, when the user returns to this page, we can compare the value stored in the session versus a fresh computation of the IP address and browser type. If the two don't match, we potentially have a hijacker, so we pick a new ID and clear out any saved data for that session. That way, the hijacker cannot retrieve any of the private information stored in the session. This doesn't cause a problem for legitimate users, because they aren't going to change browser or IP addresses in the middle of a session with your web site.</P>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-FIG-9">Figure 14-9</a> shows the newly created session the first time the script runs.</p>
<a name="learnphpmysql-CHP-14-FIG-9"></a><P><center>
<h5 class="docFigureTitle">Figure 14-9. The session is created and validates since it is a new session</h5>
<img border="0" alt="" width="494" height="227" SRC="images/learnphpmysql_1409.jpg">
</center></p><BR>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-FIG-10">Figure 14-10</a> shows what happens if the same script is executed again right away from the same browser.</p>
<a name="learnphpmysql-CHP-14-FIG-10"></a><P><center>
<h5 class="docFigureTitle">Figure 14-10. The session is valid</h5>
<img border="0" alt="" width="494" height="227" SRC="images/learnphpmysql_1410.jpg">
</center></P><BR>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-FIG-11">Figure 14-11</a> mixes things up by copying the session ID cookie from the browser in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-9">Figure 14-9</a> and setting Internet Explorer on the same client machine to send a request with the same session ID.</p>
<a name="learnphpmysql-CHP-14-FIG-11"></a><P><center>
<h5 class="docFigureTitle">Figure 14-11. The browser type change is caught</h5>
<img border="0" alt="" width="549" height="204" SRC="images/learnphpmysql_1411.jpg">
</center></P><BR>
<p class="docText">Because our script checks the type of browser, and it's changed from Firefox to Internet Explorer, the session is regenerated to prevent a security lapse.</p>

<a name="learnphpmysql-CHP-14-SECT-2.2"></a>
<h4 id="title-IDA0SG1H" class="docSection2Title">14.2.2. Trusting User Data</h4>
<a name="IDX-CHP-14-0650"></a> 
<a name="IDX-CHP-14-0651"></a> 

<p class="docText">You know that trusting data from a user isn't a great idea. But what exactly do you consider to be user data versus system data that you trust?</p>
<dl class="docList">
<dt><BR><p><span class="docPubcolor"><span class="docPubcolor"><span class="docMonofont">GET</span></span></span></P></dt>
<dd><p class="docList">Data from <tt>GET</tt> operations is inherently user data since it usually comes from form submissions.</p></dd>

<dt><br><P><span class="docPubcolor"><span class="docPubcolor"><span class="docMonofont">POST</span></span></span></P></dt>
<dd><p class="docList">Data from <tt>POST</tt> operations is inherently user data since it usually comes from form submissions.</p></dd>

<dt><BR><p><span class="docPubcolor"><span class="docEmphasis">Cookies</span></span></p></dt>
<dd><p class="docList">Cookies may seem like they could be trusted since they are automatically sent, but in reality, since they are stored on the client's computer, they could be intentionally altered. Therefore, they're considered user data.</p></dd>

<dt><br><p><span class="docPubcolor"><span class="docEmphasis">Session data</span></span></p></dt>
<dd><p class="docList">Session data can be trusted as long as the session value is set based on validated data. If it's set to a user-supplied value without validation, it's not trustworthy.</p></dd>
</dl>
<p class="docText">User input should be checked and escaped properly. Data that's bound for the database must have all special characters such as single and double quotes escaped. If PHP is not running with magic quotes on (discussed later in this chapter), then you'll need to pass user input through <tt>addslashes</tt> before sending it to the database.</p>
<p class="docText">Any user input that displays should be checked for embedded HTML that could be used for cross-site scripting attacks. The <tt>htmlspecialcharacters</tt> function is useful for escaping characters that have special meaning in HTML like less than (<tt>&lt;</tt>) and greater than (<tt>&gt;</tt>).</p>

<a name="learnphpmysql-CHP-14-SECT-2.3"></a>
<h4 id="title-IDAHVG1H" class="docSection2Title">14.2.3. Shared Hosting Concerns</h4>
<a name="IDX-CHP-14-0652"></a> 
<a name="IDX-CHP-14-0653"></a> 
<a name="IDX-CHP-14-0654"></a> 

<p class="docText">If you don't have your own dedicated server or are on a server that has multiple users, it can be very dangerous to use the default PHP settings to store your user's session data in a temporary directory. Normally, all users have access<a name="IDX-CHP-14-0655"></a> 
 to that temporary directory, so they can easily pilfer private data from the session, including the session ID.</p>
<p class="docText">To make your session data more secure, you can set the <tt>session.save_path</tt> configuration parameter with the <tt>ini_set</tt> function to change the path where sessions are stored, as shown in <a class="docLink" href="#learnphpmysql-CHP-14-EX-9">Example 14-9</a>. Make sure that these are stored below the web root directory.</P>
<a name="learnphpmysql-CHP-14-EX-9"></a><h5 id="title-IDARWG1H" class="docExampleTitle">Example 14-9. session.save_path functionality</h5><P><table cellspacing="0" width="90%" border="1" cellpadding="5"><TR><td>

<pre>
&lt;?php
    ini_set('session.save_path', '/home/user/sessions/');
    session_start();
?&gt;
</pre><BR>

</td></tr></table></p>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-EX-9">Example 14-9</a> stores the sessions in the <span class="docEmphasis">/home/user/sessions</span> directory. Be sure that whichever folder you choose is created and has the correct permissions for the PHP interpreter to write the session data. Typically, this means the file must be writable by the permission group <tt>www-data</tt>. This folder shouldn't be readable or writable by general users at large.</P>

<a name="learnphpmysql-CHP-14-SECT-2.4"></a>
<h4 id="title-IDAGXG1H" class="docSection2Title">14.2.4. Preventing Access to the Database</H4>
<p class="docText">There are a couple of ways to reduce the chance that a malicious user can access your database. First, if there is a problem connecting to the database, the default MySQL error code reveals the location of the databasein other words, the IP address of the host. You'd like to suppress that information.</p>
<p class="docText">To prevent the standard error message from PHP, add the Error Control Operator, which is the at sign (<tt>@</tt>), to the front of the database function call. You'll experience a more closed-lipped or dubious error message in <a class="docLink" href="#learnphpmysql-CHP-14-EX-10">Example 14-10</a> before calling <tt>die</tt> to stop all processing.</p>
<a name="learnphpmysql-CHP-14-EX-10"></a><H5 id="title-IDA0XG1H" class="docExampleTitle">Example 14-10. Suppressing the standard database error message</H5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><TR><td>

<pre>
&lt;?php
require_once('db_login.php');
$error = "Site down for maintenance, please check back.";
$db_link = @mysql_connect($db_host, $db_username, $db_password) or die($error);
@mysql_select_db($db_database, $db_link) or die($error);
?&gt;
</pre><br>

</TD></TR></table></p>
<p class="docText">Without the at sign (<tt>@</tt>) before the function calls, you'll see <a class="docLink" href="#learnphpmysql-CHP-14-FIG-12">Figure 14-12</a>.</p>
<a name="learnphpmysql-CHP-14-FIG-12"></a><p><center>
<h5 class="docFigureTitle">Figure 14-12. The database server's location is revealed in the error message</H5>
<img border="0" alt="" width="549" height="203" SRC="images/learnphpmysql_1412.jpg">
</center></p><BR>
<p class="docText">From a security standpoint, notice how little the error message in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-13">Figure 14-13</a> reveals to a potential attacker about the environment.</p>
<a name="learnphpmysql-CHP-14-FIG-13"></a><p><center>
<H5 class="docFigureTitle">Figure 14-13. We no longer give out more information than is necessary</H5>
<img border="0" alt="" width="549" height="156" SRC="images/learnphpmysql_1413.jpg">
</center></p><BR>
<p class="docText">While this may seem like a minor point, minimizing information available to hackers makes getting in much harder, providing you with more security.</p>

<a name="learnphpmysql-CHP-14-SECT-2.5"></a>
<h4 id="title-IDATZG1H" class="docSection2Title">14.2.5. Blocking Access to the Database for External Hosts</h4>
<a name="IDX-CHP-14-0656"></a> 
<a name="IDX-CHP-14-0657"></a> 
<a name="IDX-CHP-14-0658"></a> 

<p class="docText">If your MySQL database server is on the same host as the web server, then it makes good sense to block access to the database port for external users. This can be done through the firewall setup utilities that are part of your operating system. The standard TCP/IP port number for MySQL is 3306. The <span class="docEmphasis">port number</span> is used to differentiate between services on the same host.</p>

<a name="learnphpmysql-CHP-14-SECT-2.6"></a>
<h4 id="title-IDAQ0G1H" class="docSection2Title">14.2.6. Create Separate Database Users</h4>
<p class="docText">If you're running more than one application on your server, you should set up separate<a name="IDX-CHP-14-0659"></a> 
 database users within MySQL for each application. That way, if there is a security breach in one of the applications, the data for the other application wouldn't be compromised. For example, if you have a bookstore web site, you can create all of your database objects to be accessible from a bookstore database account. Another site for employees to check their timesheets could then be set up using a separate database login. Each application continues to work well, and in the event of a security breach, the extent of damage is limited.</p>

<a name="learnphpmysql-CHP-14-SECT-2.7"></a>
<h4 id="title-IDAA1G1H" class="docSection2Title">14.2.7. Magic Quotes</h4>
<p class="docText">PHP attempts to shield developers from the danger of special characters being used in user input by a process called <span class="docEmphasis">magic quotes</span>.<a name="IDX-CHP-14-0660"></a> 
<a name="IDX-CHP-14-0661"></a> 
 The escape characters such as single quotes (<tt>'</tt>) and double quotes (<tt>"</tt>) are escaped with slashes (<tt>\</tt>). By default, any data that comes from <tt>GET, POST</tt>, and cookies operations is automatically escaped. The escaping process is the same using the <tt>addslashes</tt> function on a string. When you send data that has special characters escaped to MySQL for insertion, MySQL automatically knows to convert the string back to the original values for storage in the database.</p>
<p class="docText">While magic quotes are good for beginners, they tend to create as many problems as they solve. Specifically, they waste some processing time, since all input is escaped regardless of whether it is bound for a database or may have been displayed.</p>
<p class="docText"><a class="docLink" href="#learnphpmysql-CHP-14-EX-11">Example 14-11</a> shows how magic quotes add an escape character to a value collected from a form.</p>
<a name="learnphpmysql-CHP-14-EX-11"></a><H5 id="title-IDAH2G1H" class="docExampleTitle">Example 14-11. Seeing the results of magic quotes</h5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><TR><TD>

<pre>
&lt;?php
$search=$_GET[search];
$self=$_SERVER['PHP_SELF'];
if ($search != NULL )
{
  echo "The search string is: &lt;strong&gt;$search&lt;/strong&gt;.";
}
else
{
  echo ("&lt;form action=\"$self\" ");
  echo ('method="get"&gt;
         &lt;label&gt; Search: &lt;input type="text" name="search" id="search"&gt; &lt;/label&gt;
         &lt;input type="submit" value="Go!"&gt;
         &lt;/form&gt;
        ');
}
?&gt;
</pre><br>

</TD></tr></table></p>
<p class="docText">The entry in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-14">Figure 14-14</a> returns the screen in <a class="docLink" href="#learnphpmysql-CHP-14-FIG-15">Figure 14-15</a>.</p>
<a name="learnphpmysql-CHP-14-FIG-14"></a><P><center>
<h5 class="docFigureTitle">Figure 14-14. Sending some test data with special characters</H5>
<img border="0" alt="" width="549" height="179" SRC="images/learnphpmysql_1414.jpg">
</center></p><br>
<a name="learnphpmysql-CHP-14-FIG-15"></a><P><center>
<H5 class="docFigureTitle">Figure 14-15. The string has its special characters escaped</h5>
<img border="0" alt="" width="549" height="179" SRC="images/learnphpmysql_1415.jpg">
</center></P><br>
<p class="docText">Another annoyance with magic quotes is that you can't always assume <tt>magic_quotes</tt> are enabled if you're writing PHP code that might end up being installed on a variety of servers. The solution is to check whether it is enabled from within your code and call <tt>addslashes</tt> manually if it isn't. To check to see whether <tt>magic_quotes</tt> escaping is active, use the <tt>get_magic_quotes_gpc</tt> function. <a class="docLink" href="#learnphpmysql-CHP-14-EX-12">Example 14-12</a> shows how to check for magic quotes and call <tt>add_slashes</tt> if they are off.</p>
<a name="learnphpmysql-CHP-14-EX-12"></a><H5 id="title-IDAH4G1H" class="docExampleTitle">Example 14-12. Checking for magic quotes</H5><p><table cellspacing="0" width="90%" border="1" cellpadding="5"><tr><td>

<pre>
&lt;?php
$search = $_GET["search"];
if (!get_magic_quotes_gpc()) {
$search = addslashes($search);
}
if ($search != NULL ){
echo "The search string is: &lt;strong&gt;$search&lt;/strong&gt;.";
}
else {
echo '&lt;form method="'.$_SERVER["PHP_SELF"].'" method="GET"&gt;
&lt;label&gt;
Search:
&lt;input type="text" name="search" id="search" /&gt;
&lt;/label&gt;
&lt;input type="submit" value="Go!" /&gt;
&lt;/form&gt;';
}
?&gt;
</pre><br>

</TD></tr></table></P>
<p class="docText">Again, whether magic quotes are enabled or not, it's up to you to be knowledgeable about how PHP and MySQL treat special characters. Be sure that your site not only works but is secure.</p>
<p class="docText">We've covered security and numerous issues to help you secure your web site. Next, we'll be discussing validation and error handling. We're very close to creating your blog. How exciting!</p>


</TD></TR></table>
<br>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14-SECT-1.html><img src="images/prev.gif" width="60" height="17" border="0" align="absmiddle" alt="Previous Page"></a>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href=learnphpmysql-CHP-14-SECT-3.html><img src="images/next.gif" width="60" height="17" border="0" align="absmiddle" alt="Next Page"></a>
</div></td></tr></table>
<script type="text/javascript"><!--
google_ad_client = "pub-0203281046321155";
google_alternate_ad_url = "http://www.bookhtml.com/adbrite.htm";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="4867465545";
google_color_border = "FFFFFF";
google_color_link = "0000FF";
google_color_bg = "FFFFFF";
google_color_text = "000000";
google_color_url = "0000FF";
//--></script>
<script type="text/javascript"
  src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</html>
